package com.zzyq.pc.mongodb.dao;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.mongodb.morphia.query.Query;

import com.zzyq.pc.common.enums.Channel;
import com.zzyq.pc.mongodb.model.MongodbDate;
import com.zzyq.pc.utils.MongoHelper;
import com.zzyq.pc.web.analysis.model.Analysis;

public class MongodbOperation {
	MongoHelper mongodb = MongoHelper.getInstance();

	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

	/**
	 * 获取查询单位时间内目标方案信息的Query
	 * 
	 * @param entity
	 * @param IfmIds
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public Query<?> getQueryByifmIdsAndTime(Class<?> entity, List<String> IfmIds, Long startTime, Long endTime) {
		Query<?> query = mongodb.getDatastore().createQuery(entity);
		query.criteria("ifmId").in(IfmIds);
		query.criteria("sort_timestamp").greaterThanOrEq(startTime);
		query.criteria("sort_timestamp").lessThanOrEq(endTime);
		return query;
	}

	/**
	 * 分析 获取时间范围内传入方案的总数、正面数、负面数。
	 * 
	 * @param entity
	 *            mongodbDate映射类
	 * @param allIfmIds
	 *            所有的方案ID集合
	 * @param negativeIfmIds
	 *            敏感的方案ID集合
	 * @param startTime
	 *            开始时间
	 * @param endTime
	 *            结束时间
	 * @return Analysis对象
	 */
	private Analysis wholeSentiment(Class<?> entity, List<String> allIfmIds, List<String> negativeIfmIds,
			Long startTime, Long endTime) {
		Analysis analysis = new Analysis();
		Integer number = null;
		Integer positiveNumber = null;
		Integer negativeNumber = null;
		Query<?> query = getQueryByifmIdsAndTime(entity, allIfmIds, startTime, endTime);
		number = (int) query.count();
		Query<?> negativeQuery = getQueryByifmIdsAndTime(entity, negativeIfmIds, startTime, endTime);
		negativeNumber = (int) negativeQuery.count();
		positiveNumber = number - negativeNumber;
		analysis.setDate(format.format(startTime));
		analysis.setNegativeNumber(negativeNumber);
		analysis.setNumber(number);
		analysis.setPositiveNumber(positiveNumber);
		return analysis;
	}

	/**
	 * 网络舆情分析 获取时间范围内传入方案+查询类型的总数、正面数、负面数。
	 * 
	 * @param entity
	 *            mongodbDate映射类
	 * @param allIfmIds
	 *            所有的方案ID集合
	 * @param negativeIfmIds
	 *            敏感的方案ID集合
	 * @param startTime
	 *            开始时间
	 * @param endTime
	 *            结束时间
	 * @param articleTypes
	 *            渠道类型集合
	 * @return Analysis对象
	 */
	public Analysis networkSentiment(Class<?> entity, List<String> allIfmIds, List<String> negativeIfmIds,
			Long startTime, Long endTime, Set<String> articleTypes) {
		Analysis analysis = new Analysis();
		Integer number = null;
		Integer positiveNumber = null;
		Integer negativeNumber = null;
		Query<?> query = getQueryByifmIdsAndTime(entity, allIfmIds, startTime, endTime);
		if (null != articleTypes && !articleTypes.isEmpty()) {
			query.criteria("articleType").in(articleTypes);
		} else {
			articleTypes.clear();
			articleTypes.add(Channel.NEWS.getName());
			query.criteria("articleType").notIn(articleTypes);
		}
		number = (int) query.count();
		Query<?> negativeQuery = getQueryByifmIdsAndTime(entity, negativeIfmIds, startTime, endTime);
		negativeQuery.criteria("articleType").in(articleTypes);
		negativeNumber = (int) negativeQuery.count();
		positiveNumber = number - negativeNumber;
		analysis.setDate(format.format(startTime));
		analysis.setNegativeNumber(negativeNumber);
		analysis.setNumber(number);
		analysis.setPositiveNumber(positiveNumber);
		return analysis;
	}

	/**
	 * 媒体舆情分析 获取时间范围内传入方案的总数、正面数、负面数。
	 * 
	 * @param entity
	 *            mongodbDate映射类
	 * @param allIfmIds
	 *            所有的方案ID集合
	 * @param negativeIfmIds
	 *            敏感的方案ID集合
	 * @param startTime
	 *            开始时间
	 * @param endTime
	 *            结束时间
	 * @return Analysis对象
	 */
	public Analysis mediaSentiment(Class<?> entity, List<String> allIfmIds, List<String> negativeIfmIds, Long startTime,
			Long endTime) {
		Analysis analysis = new Analysis();
		Integer number = null;
		Integer positiveNumber = null;
		Integer negativeNumber = null;
		Query<?> query = getQueryByifmIdsAndTime(entity, allIfmIds, startTime, endTime);
		query.criteria("articleType").equal(Channel.NEWS.getName());
		number = (int) query.count();
		Query<?> negativeQuery = getQueryByifmIdsAndTime(entity, negativeIfmIds, startTime, endTime);
		negativeQuery.criteria("articleType").equal(Channel.NEWS.getName());
		negativeNumber = (int) negativeQuery.count();
		positiveNumber = number - negativeNumber;
		analysis.setDate(format.format(startTime));
		analysis.setNegativeNumber(negativeNumber);
		analysis.setNumber(number);
		analysis.setPositiveNumber(positiveNumber);
		return analysis;
	}

	/**
	 * mediaSentiment方法的封装 媒体舆情分析调用此方法
	 * 
	 * @param entity
	 *            mongodbDate映射类
	 * @param allIfmIds
	 *            所有的方案ID集合
	 * @param negativeIfmIds
	 *            敏感的方案ID集合
	 * @param starDate
	 *            开始的日期（yyyy-MM-dd）
	 * @param endDate
	 *            结束的日期（yyyy-MM-dd）
	 * @return Analysis对象
	 */
	public List<Analysis> getMediaSentiment(Class<?> entity, List<String> allIfmIds, List<String> negativeIfmIds,
			String starDate, String endDate) {
		List<Analysis> AnalysisList = new ArrayList<Analysis>();
		Analysis a = new Analysis();
		DateTime dt = new DateTime(starDate);
		DateTime dt1 = new DateTime(endDate);
		Duration duration = new Duration(dt, dt1);
		for (int i = 0; i <= duration.getStandardDays(); i++) {
			a = mediaSentiment(MongodbDate.class, allIfmIds, negativeIfmIds, dt.plusDays(i).getMillis(),
					dt.plusDays(i + 1).getMillis());
			AnalysisList.add(a);
		}
		return AnalysisList;
	}

	/**
	 * networkSentiment方法的封装 网络舆情分析调用此方法
	 * 
	 * @param entity
	 *            mongodbDate映射类
	 * @param allIfmIds
	 *            所有的方案ID集合
	 * @param negativeIfmIds
	 *            敏感的方案ID集合
	 * @param starDate
	 *            开始的日期（yyyy-MM-dd）
	 * @param endDate
	 *            结束的日期（yyyy-MM-dd）
	 * @param articleTypes
	 *            渠道类型集合
	 * @return Analysis对象
	 */
	public List<Analysis> getNetworkSentiment(Class<?> entity, List<String> allIfmIds, List<String> negativeIfmIds,
			String starDate, String endDate, Set<String> articleTypes) {
		List<Analysis> AnalysisList = new ArrayList<Analysis>();
		Analysis a = new Analysis();
		DateTime dt = new DateTime(starDate);
		DateTime dt1 = new DateTime(endDate);
		Duration duration = new Duration(dt, dt1);
		for (int i = 0; i <= duration.getStandardDays(); i++) {
			a = networkSentiment(MongodbDate.class, allIfmIds, negativeIfmIds, dt.plusDays(i).getMillis(),
					dt.plusDays(i + 1).getMillis(), articleTypes);
			AnalysisList.add(a);
		}
		return AnalysisList;
	}

	/**
	 * wholeSentiment方法的封装 整体舆情分析调用此方法
	 * 
	 * @param entity
	 *            mongodbDate映射类
	 * @param allIfmIds
	 *            所有的方案ID集合
	 * @param negativeIfmIds
	 *            敏感的方案ID集合
	 * @param starDate
	 *            开始的日期（yyyy-MM-dd）
	 * @param endDate
	 *            结束的日期（yyyy-MM-dd）
	 * @return List<Analysis> 对象集合
	 */
	public List<Analysis> getWholeSentiment(Class<?> entity, List<String> allIfmIds, List<String> negativeIfmIds,
			String starDate, String endDate) {
		List<Analysis> AnalysisList = new ArrayList<Analysis>();
		Analysis a = new Analysis();
		DateTime dt = new DateTime(starDate);
		DateTime dt1 = new DateTime(endDate);
		Duration duration = new Duration(dt, dt1);
		for (int i = 0; i <= duration.getStandardDays(); i++) {
			a = wholeSentiment(MongodbDate.class, allIfmIds, negativeIfmIds, dt.plusDays(i).getMillis(),
					dt.plusDays(i + 1).getMillis());
			AnalysisList.add(a);
		}
		return AnalysisList;
	}

	/**
	 * 分析 获取单位时间内传入的方案ID集合中渠道的分发数 用做渠道饼图数据
	 * 
	 * @param entity
	 *            mongodbDate映射类
	 * @param allIfmIds
	 *            方案ID集合
	 * @param startTime
	 *            开始时间
	 * @param endTime
	 *            结束时间
	 * @param articleTypes
	 *            需要查询的渠道集合
	 * @return 数量集合
	 */
	public Map<String, Integer> distribution(Class<?> entity, List<String> allIfmIds, Long startTime, Long endTime,
			Set<String> articleTypes) {
		Map<String, Integer> map = new HashMap<String, Integer>();
		if (articleTypes != null && !articleTypes.isEmpty()) {
			for (String articleType : articleTypes) {
				Query<?> query = getQueryByifmIdsAndTime(entity, allIfmIds, startTime, endTime);
				query.criteria("articleType").equal(articleType);
				map.put(articleType, (int) query.count());
			}
		} else {
			for (Channel str : Channel.values()) {
				// if (!str.getName().equals(Channel.NEWS.getName())) {
					Query<?> query = getQueryByifmIdsAndTime(entity, allIfmIds, startTime, endTime);
					query.criteria("articleType").equal(str.getName());
					map.put(str.getName(), (int) query.count());
				// }
			}
		}
		return map;
	}

	public static void main(String[] args) {
		Long startTime = null;
		Long endTime = null;
		DateTime dtstarDate = new DateTime("2017-8-18");
		DateTime dtendDate = new DateTime("2017-8-19");
		startTime = dtstarDate.withMillisOfDay(0).getMillis();
		endTime = dtendDate.plusDays(1).withMillisOfDay(0).getMillis();
		System.out.println(startTime);
		System.out.println(endTime);
	}
}
